<template>
  <div class="fuzzy-search">
              <q-select
                class="select input-select"
                :class="{'margin-b-20': !isForm && !isFilter}"
                v-model="fuzzyData"
                outlined
                hide-selected
                :rules="rules"
                use-input
                fill-input
                input-debounce="1000"
                :options="fuzzyOptions"
                @input="onInput"
                @filter="filterFn"
                @popup-hide="popUpHide"
                :option-disable="item => disableOption(item.value)"
                :placeholder="`${hint? hint: place + title}`"
                dense
                options-dense
                clearable
                :disable="disable"
                emit-value
                map-options
                type="text"
              >
              <template v-slot:option="scope">
                  <q-item
                    v-bind="scope.itemProps"
                    v-on="scope.itemEvents"
                  >
                    <q-item-section>
                      <q-item-label v-html="scope.opt.label" ></q-item-label>
                    </q-item-section>
<!--                    <q-item-section side v-if="isShowValue">-->
<!--                      <q-item-label v-html="scope.opt.fuzzyValue" />-->
<!--                    </q-item-section>-->
                  </q-item>
                </template>
                <template v-if="showLabel" v-slot:before>
                  <label class="text-right name label-width font-size-16" :class="{'large-label': !smallSize }" v-if="isForm && rules.length">
                        <span class="text-red" v-if="isShowTextRed">*</span><span class="text-black">{{title}}:</span>
                  </label>
                  <span v-else class="form-name" :style="{ width: isForm ? '100px' :  '' }">{{title}}:</span>
                </template>
              </q-select>
  </div>
</template>

<script>
import _ from 'lodash'
export default {
  name: 'fuzzy-search',
  props: {
    value: [Array, String, Number],
    title: String, // 搜索框名称
    place: {
      type: String,
      default: '请选择'
    },
    isShowValue: { // 是否显示value值, ,默认true, label - value
      type: Boolean,
      default: true
    },
    isForm: { // 是否提交表单
      type: Boolean,
      default: false
    },
    isFilter: { // 是否提交表单
      type: Boolean,
      default: false
    },
    disable: { // 是否提交表单
      type: Boolean,
      default: false
    },
    hint: { // 占位符
      type: String,
      default: ''
    },
    fuzzyFunc: Function,
    // 动态参数合集
    // 需要多余参数
    fuzzyParams: Object,
    // 增加的key 值
    fuzzyNumber: {
      type: String,
      default: 'deviceNameOrNumber'
    },
    options: Array, // 用来做sb似的回显
    rules: {
      type: Array,
      default: () => {
        return []
      }
    },
    selList: {
      type: Array,
      default: () => {
        return []
      }
    }, // 已选项
    fuzzyObj: {
      type: Array,
      default: () => {
        return ['label', 'value']
      }
    },
    // 显示右侧的值
    fuzzyValue: String,
    smallSize: {
      type: Boolean,
      default: false
    },
    isShowTextRed: {
      type: Boolean,
      default: true
    },
    showAllOption: {
      type: Boolean,
      default: true
    },
    showLabel: {
      type: Boolean,
      default: true
    },
    // 是否显示规格
    showSpec: {
      type: Boolean,
      default: false
    },
    // 通过前端过滤
    filterByFe: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      fuzzyData: null,
      fuzzyOptions: []
    }
  },
  watch: {
    value: {
      handler (val) {
        this.fuzzyData = val
      },
      deep: true,
      immediate: true
    },
    fuzzyData: {
      deep: true,
      handler () {
        this.$emit('input', this.fuzzyData)
      }
    },
    // 编辑时回显赋值
    options: {
      immediate: true,
      handler: function (newPro) {
        !_.isEmpty(newPro) && (this.fuzzyOptions = this.setFuzzyoptions(newPro))
      }
    }
  },
  computed: {
  },
  methods: {
    // 模糊搜索
    filterFn (val, update, abort) {
      // 按道理讲模糊搜索不添加其他的参数, 但是查设备这个是个意外暂时额外的参数写为deviceNameOrNumber
      // 后期如果还有别的 , 就将其写为动态
      // 算了, 现在就写为活的吧
      let member
      if (_.isNil(this.fuzzyParams)) {
        member = val
      } else {
        member = { ...this.fuzzyParams }
        member[this.fuzzyNumber] = val
      }
      const fuzzyFunc = this.filterByFe ? this.getFilter : this.fuzzyFunc
      fuzzyFunc(member).then(res => {
        let ret = Array.isArray(res.data) ? res.data : (res?.data?.list || res?.list || [])
        let listData = this.showAllOption ? this.setFuzzyoptions(ret) : this.setFuzzyoptions(ret).slice(0, 10)
        if (!listData.length) {
          this.fuzzyData = null
        }
        update(() => {
          // 最多显示10项
          if (val) {
            this.fuzzyOptions = listData
          } else {
            this.fuzzyOptions = _.isEmpty(this.options) ? listData : this.setOptionsItem(listData)
          }
        })
      })
    },
    popUpHide () {
      const filterList = this.fuzzyOptions.filter(val => val.value === this.fuzzyData)
      if (!filterList.length) {
        this.fuzzyData = null
      }
    },
    // 编辑回显时判断是否存在top10中
    setOptionsItem (val) {
      const member = _.get(this.options[0], 'value')
      return val.some(v => v.value === member) ? val : (this.showAllOption ? [...this.options, ...val] : [...this.options, ...val].slice(0, 10))
    },
    setFuzzyoptions (val) {
      return val.map(v => {
        const item = v
        item.fuzzyValue = _.isEmpty(this.fuzzyValue) ? v[this.fuzzyObj[1]] : v[this.fuzzyValue]
        item.label = this.isShowValue ? `${v[this.fuzzyObj[0]]}(${item.fuzzyValue})` : v[this.fuzzyObj[0]]
        this.showSpec && (item.label += `/${this.$utils.label(item.productStandard)}`)
        item.value = v[this.fuzzyObj[1]]
        return item
      })
    },
    onInput (val) {
      this.$emit('onSelect', val, this.fuzzyOptions)
    },
    getFilter (val) {
      return new Promise(resolve => {
        const res = {
          code: '1200',
          data: [],
          message: ''
        }
        if (val) {
          setTimeout(() => {
            res.data = this.options.filter(item => {
              return item[this.fuzzyObj[0]].toLowerCase().indexOf(val.toLowerCase()) > -1
            })
            resolve(res)
          }, 200)
        } else {
          setTimeout(() => {
            res.data = this.options
            resolve(res)
          }, 200)
        }
      })
    },
    disableOption (val) {
      return _.includes(this.selList, val)
    }
  },
  mounted () {

  }
}
</script>

<style scoped lang="stylus">
.large-label{
  width 100px
}
</style>
